"""
飞书页面结构分析工具
使用Playwright分析飞书知识库页面的DOM结构
"""

import asyncio
import json
from playwright.async_api import async_playwright
import logging

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class FeishuStructureAnalyzer:
    """飞书页面结构分析器"""
    
    def __init__(self, url: str):
        """
        初始化分析器
        
        Args:
            url: 要分析的飞书页面URL
        """
        self.url = url
        self.structure_data = {}

    async def analyzePageStructure(self, page) -> dict:
        """
        分析页面的整体结构
        
        Args:
            page: Playwright页面对象
            
        Returns:
            页面结构数据
        """
        logger.info("开始分析页面整体结构...")
        
        # 获取页面基本信息
        structure = {
            'url': page.url,
            'title': await page.title(),
            'viewport': page.viewport_size,
            'main_sections': {},
            'navigation_elements': {},
            'sidebar_structure': {},
            'content_areas': {}
        }
        
        # 分析主要区域
        await self.analyzeMainSections(page, structure)
        
        # 分析导航元素
        await self.analyzeNavigationElements(page, structure)
        
        # 分析侧边栏结构
        await self.analyzeSidebarStructure(page, structure)
        
        # 分析内容区域
        await self.analyzeContentAreas(page, structure)
        
        return structure

    async def analyzeMainSections(self, page, structure):
        """分析页面主要区域"""
        logger.info("分析页面主要区域...")
        
        # 常见的页面区域选择器
        section_selectors = {
            'header': ['header', '.header', '#header', '[role="banner"]'],
            'navigation': ['nav', '.nav', '.navigation', '[role="navigation"]'],
            'sidebar': ['.sidebar', '.side-panel', '.left-panel', '.navigation-panel'],
            'main_content': ['main', '.main', '.content', '.main-content', '[role="main"]'],
            'footer': ['footer', '.footer', '#footer', '[role="contentinfo"]']
        }
        
        for section_name, selectors in section_selectors.items():
            structure['main_sections'][section_name] = []
            
            for selector in selectors:
                try:
                    elements = await page.query_selector_all(selector)
                    for i, element in enumerate(elements):
                        if await element.is_visible():
                            bbox = await element.bounding_box()
                            class_attr = await element.get_attribute('class') or ''
                            id_attr = await element.get_attribute('id') or ''
                            
                            structure['main_sections'][section_name].append({
                                'selector': selector,
                                'index': i,
                                'class': class_attr,
                                'id': id_attr,
                                'bounding_box': bbox,
                                'visible': True
                            })
                except Exception as e:
                    logger.debug(f"分析区域 {section_name} 选择器 {selector} 时出错: {str(e)}")

    async def analyzeNavigationElements(self, page, structure):
        """分析导航相关元素"""
        logger.info("分析导航元素...")
        
        # 导航相关的选择器
        nav_selectors = {
            'breadcrumb': ['.breadcrumb', '.breadcrumbs', '[aria-label*="breadcrumb"]'],
            'menu_items': ['[role="menuitem"]', '.menu-item', '.nav-item'],
            'dropdowns': ['.dropdown', '.select', '[role="listbox"]'],
            'tabs': ['.tab', '.tabs', '[role="tab"]', '[role="tablist"]'],
            'tree_nodes': ['.tree-node', '.tree-item', '[role="treeitem"]']
        }
        
        for nav_type, selectors in nav_selectors.items():
            structure['navigation_elements'][nav_type] = []
            
            for selector in selectors:
                try:
                    elements = await page.query_selector_all(selector)
                    for element in elements:
                        if await element.is_visible():
                            text = await element.inner_text()
                            href = await element.get_attribute('href')
                            aria_expanded = await element.get_attribute('aria-expanded')
                            
                            structure['navigation_elements'][nav_type].append({
                                'selector': selector,
                                'text': text.strip()[:100] if text else '',
                                'href': href,
                                'aria_expanded': aria_expanded,
                                'has_children': aria_expanded is not None
                            })
                except Exception as e:
                    logger.debug(f"分析导航元素 {nav_type} 时出错: {str(e)}")

    async def analyzeSidebarStructure(self, page, structure):
        """详细分析侧边栏结构"""
        logger.info("详细分析侧边栏结构...")
        
        # 查找侧边栏
        sidebar_selectors = [
            '.sidebar', '.side-panel', '.left-panel', '.navigation-panel',
            '[class*="sidebar"]', '[class*="side"]', '[class*="nav"]'
        ]
        
        for selector in sidebar_selectors:
            try:
                sidebar = await page.query_selector(selector)
                if sidebar and await sidebar.is_visible():
                    logger.info(f"找到侧边栏: {selector}")
                    
                    # 分析侧边栏内部结构
                    sidebar_info = await self.analyzeSidebarContent(sidebar)
                    structure['sidebar_structure'][selector] = sidebar_info
                    break
            except Exception as e:
                logger.debug(f"分析侧边栏选择器 {selector} 时出错: {str(e)}")

    async def analyzeSidebarContent(self, sidebar_element):
        """分析侧边栏内容"""
        sidebar_info = {
            'tree_structure': [],
            'expandable_nodes': [],
            'document_links': [],
            'folder_structure': {}
        }
        
        try:
            # 查找树形结构元素
            tree_selectors = [
                '.tree', '.tree-node', '.tree-item',
                '[role="tree"]', '[role="treeitem"]',
                '.lark-tree', '.directory'
            ]
            
            for selector in tree_selectors:
                elements = await sidebar_element.query_selector_all(selector)
                for element in elements:
                    text = await element.inner_text()
                    class_attr = await element.get_attribute('class') or ''
                    data_attrs = await element.evaluate('''
                        el => {
                            const attrs = {};
                            for (let attr of el.attributes) {
                                if (attr.name.startsWith('data-')) {
                                    attrs[attr.name] = attr.value;
                                }
                            }
                            return attrs;
                        }
                    ''')
                    
                    sidebar_info['tree_structure'].append({
                        'selector': selector,
                        'text': text.strip()[:100] if text else '',
                        'class': class_attr,
                        'data_attributes': data_attrs
                    })
            
            # 查找可展开的节点
            expandable_selectors = [
                'svg[data-icon*="triangle"]', 'svg[data-icon*="caret"]',
                '.expand', '.collapse', '.toggle',
                '[aria-expanded]', '[role="button"]'
            ]
            
            for selector in expandable_selectors:
                elements = await sidebar_element.query_selector_all(selector)
                for element in elements:
                    aria_expanded = await element.get_attribute('aria-expanded')
                    parent_text = ''
                    try:
                        parent = await element.query_selector('..')
                        if parent:
                            parent_text = await parent.inner_text()
                    except:
                        pass
                    
                    sidebar_info['expandable_nodes'].append({
                        'selector': selector,
                        'aria_expanded': aria_expanded,
                        'parent_text': parent_text.strip()[:50] if parent_text else ''
                    })
            
            # 查找文档链接
            link_selectors = ['a[href]']
            for selector in link_selectors:
                elements = await sidebar_element.query_selector_all(selector)
                for element in elements:
                    href = await element.get_attribute('href')
                    text = await element.inner_text()
                    
                    if href and ('wiki' in href or 'doc' in href):
                        sidebar_info['document_links'].append({
                            'href': href,
                            'text': text.strip()[:100] if text else '',
                            'is_document': True
                        })
            
        except Exception as e:
            logger.error(f"分析侧边栏内容时出错: {str(e)}")
        
        return sidebar_info

    async def analyzeContentAreas(self, page, structure):
        """分析内容区域"""
        logger.info("分析内容区域...")
        
        content_selectors = {
            'article_content': ['article', '.article', '.doc-content', '.content'],
            'editor_areas': ['.editor', '.rich-editor', '[contenteditable]'],
            'form_elements': ['form', 'input', 'textarea', 'select', 'button'],
            'modal_dialogs': ['.modal', '.dialog', '.popup', '[role="dialog"]']
        }
        
        for content_type, selectors in content_selectors.items():
            structure['content_areas'][content_type] = []
            
            for selector in selectors:
                try:
                    elements = await page.query_selector_all(selector)
                    for element in elements:
                        if await element.is_visible():
                            bbox = await element.bounding_box()
                            text_content = await element.inner_text()
                            
                            structure['content_areas'][content_type].append({
                                'selector': selector,
                                'bounding_box': bbox,
                                'text_length': len(text_content) if text_content else 0,
                                'text_preview': text_content[:200] if text_content else ''
                            })
                except Exception as e:
                    logger.debug(f"分析内容区域 {content_type} 时出错: {str(e)}")

    async def saveStructureAnalysis(self, structure_data: dict, filename: str = 'feishu_structure_analysis.json'):
        """保存结构分析结果到JSON文件"""
        try:
            with open(filename, 'w', encoding='utf-8') as f:
                json.dump(structure_data, ensure_ascii=False, indent=2, fp=f)
            logger.info(f"页面结构分析结果已保存到: {filename}")
        except Exception as e:
            logger.error(f"保存分析结果失败: {str(e)}")

    async def printStructureSummary(self, structure_data: dict):
        """打印结构分析摘要"""
        print("\n" + "="*80)
        print("🔍 飞书知识库页面结构分析摘要")
        print("="*80)
        
        print(f"\n📍 页面信息:")
        print(f"   URL: {structure_data['url']}")
        print(f"   标题: {structure_data['title']}")
        print(f"   视口大小: {structure_data['viewport']}")
        
        print(f"\n🏗️ 主要区域:")
        for section, data in structure_data['main_sections'].items():
            if data:
                print(f"   {section}: 找到 {len(data)} 个元素")
        
        print(f"\n🧭 导航元素:")
        for nav_type, elements in structure_data['navigation_elements'].items():
            if elements:
                print(f"   {nav_type}: {len(elements)} 个")
        
        print(f"\n📂 侧边栏结构:")
        for selector, info in structure_data['sidebar_structure'].items():
            print(f"   选择器: {selector}")
            print(f"   树形结构元素: {len(info['tree_structure'])} 个")
            print(f"   可展开节点: {len(info['expandable_nodes'])} 个")
            print(f"   文档链接: {len(info['document_links'])} 个")
        
        print(f"\n📄 内容区域:")
        for content_type, areas in structure_data['content_areas'].items():
            if areas:
                print(f"   {content_type}: {len(areas)} 个区域")
        
        print("\n" + "="*80)

    async def run(self):
        """运行结构分析"""
        logger.info(f"开始分析飞书页面结构: {self.url}")
        
        async with async_playwright() as p:
            browser = await p.chromium.launch(headless=False)
            
            try:
                # 创建浏览器上下文
                context = await browser.new_context(
                    viewport={'width': 1920, 'height': 1080}
                )
                
                page = await context.new_page()
                
                # 访问页面
                await page.goto(self.url, wait_until='networkidle', timeout=30000)
                await asyncio.sleep(5)  # 等待页面完全加载
                
                # 分析页面结构
                structure_data = await self.analyzePageStructure(page)
                
                # 保存分析结果
                await self.saveStructureAnalysis(structure_data)
                
                # 打印摘要
                await self.printStructureSummary(structure_data)
                
                logger.info("页面结构分析完成")
                
                # 等待用户查看结果
                input("\n按回车键继续...")
                
            finally:
                await browser.close()

async def main():
    """主函数"""
    url = "https://my-ichery.feishu.cn/wiki/UkYtwGxOtieErfkzUKkcjx48nib"
    analyzer = FeishuStructureAnalyzer(url)
    await analyzer.run()

if __name__ == "__main__":
    asyncio.run(main()) 